package com.miage.itrading.gui;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ComponentEvent;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.swing.JInternalFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.HighLowItemLabelGenerator;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.labels.XYToolTipGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.CandlestickRenderer;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.resources.JFreeChartResources;
import org.jfree.data.xy.DefaultHighLowDataset;
import org.jfree.data.xy.XYDataset;

import com.miage.itrading.dao.CotationDAO;
import com.miage.itrading.entites.Cotation;
import com.miage.itrading.entites.Historique;
import com.miage.itrading.gui.GraphDurees.Duree;
import com.miage.itrading.metier.IndicateurSurCours;
import com.miage.itrading.metier.IndicateursSup;

public class PartieCentrale extends JInternalFrame {

	public static float X 		= 0.15f;
	public static float Y		= 0.1f;
	public static float WIDTH 	= 0.7f;
	public static float HEIGHT 	= 0.9f;

	private static final long 				serialVersionUID = -530082045952455620L;
	private Cotation					cotation;
	private Duree							duree;
	private ChartPanel chartPanel;
	private List<IndicateursSup> 				chartIndicateurs;
	private List<IndicateurSurCours>		indicateursSurCours;
	private FenetrePrincipale 				parent;
	
	private JPanel main;
	JPanel ind;
	
	public PartieCentrale(FenetrePrincipale parent) {
		super("Graphiques - iTrading",  
				true, //resizable
				true, //closable
				true, //maximizable
				true);//iconifiable

		this.parent = parent;

		setLocation((int) (parent.getScreenSize().width * X), 
				(int) (parent.getScreenSize().height * Y));

		setSize((int) (parent.getScreenSize().width * WIDTH), 
				(int) (parent.getScreenSize().height * HEIGHT));
		setResizable(true);

		chartIndicateurs 	= new ArrayList<IndicateursSup>();
		indicateursSurCours = new ArrayList<IndicateurSurCours>(); 	
		
		// Rémi : \o/
		main =(JPanel)((JLayeredPane)((Container)((Container)this.getComponent(0)).getComponent(1))).getComponent(0);
	}

	public void ajouterIndicateurSurCours(String nomIndicateur, List<Float> valeurs,int[] periodes) {
		indicateursSurCours.add(new IndicateurSurCours(nomIndicateur, valeurs, periodes, cotation));
		build();
	}

	public void ajouterIndicateur(String nomIndicateur, List<Float> valeurs,int[] periodes) {
		chartIndicateurs.add(new IndicateursSup(nomIndicateur, valeurs, periodes, cotation));
		build();
	}

	public void supprimerIndicateur(String nomIndicateur){

		for(int i = 0 ; i< chartIndicateurs.size() ; ++i){
			if (chartIndicateurs.get(i).getNomIndicateur().contains(nomIndicateur)){
				 
				ind.remove(i);
				chartIndicateurs.remove(i);
				break;
			}
		}

		build();
	}

	public void supprimerIndicateurSurCours(String nomIndicateur) {
		List<IndicateurSurCours> supprime = new ArrayList<IndicateurSurCours>();
		for(int i = 0 ; i< indicateursSurCours.size() ; ++i){
			if (indicateursSurCours.get(i).getNomIndicateur().contains(nomIndicateur)){
				supprime.add(indicateursSurCours.get(i));
			}
		}
		indicateursSurCours.removeAll(supprime);
		build();
	}

	/**
	 * Construit un graphique de "dateDebut" à "dateFin", définit les valeurs
	 * "courbes" correspondant aux courbes "noms"
	 * 
	 * @param typeGraphe
	 * @return
	 */
	public void build() {
		if (cotation != null) {
			main.removeAll();
			CotationDAO c = new CotationDAO();

			/**
			 * Vérifie que l'historique de la cotation contient assez de données pour être affiché
			 * en entier, sinon va chercher les x valeurs manquantes
			 */ 
			if (duree == Duree.INTRADAY) {
				// TODO
			} else {			
				Date ajd 		= new Date();
				Calendar histo	= Calendar.getInstance();

				if (duree == Duree.SEMAINE) {
					histo.add(Calendar.DAY_OF_MONTH, - 5);

				}
				else if (duree == Duree.MOIS) {
					histo.add(Calendar.MONTH, -1);

				}
				else if (duree == Duree.ANNEE) {
					histo.add(Calendar.YEAR, -1);

				} else if (duree == Duree.HISTORIQUE) {
					histo.add(Calendar.YEAR, -100);
				}

				try {
					afficherHistorique(c.getHistoriqueWithToday(cotation.getIdCotation(), histo.getTime(), ajd));					

				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}

	@SuppressWarnings("deprecation")
	private void afficherHistorique(final List<Historique> historique) {
		int nbHistoriques = historique.size();

		double uppest=0, lowest=0;

		Date[] date		= new Date[nbHistoriques];
		double[] high	= new double[nbHistoriques];
		double[] low	= new double[nbHistoriques];
		double[] open	= new double[nbHistoriques];
		double[] close	= new double[nbHistoriques];
		double[] volume	= new double[nbHistoriques];

		Historique h;
		for (int i=0 ; i<nbHistoriques; ++i) {

			h = historique.get(i);

			if (i == 0) {
				lowest  = h.getPlusBas();
				uppest = h.getPlusHaut();
			}

			if (h.getPlusBas() < lowest) {
				lowest = h.getPlusBas();
			}

			if (h.getPlusHaut() > uppest) {
				uppest = h.getPlusHaut();
			}


			date[i] 	= h.getDate();
			high[i]		= h.getPlusHaut();
			low[i]		= h.getPlusBas();
			open[i]		= h.getOuverture();
			close[i]	= h.getFermeture();
			volume[i]	= 0;
		}


		final DefaultHighLowDataset data = new DefaultHighLowDataset("", date, high, low, open, close, volume);


		final JFreeChart chart = ChartFactory.createCandlestickChart(cotation.getNom() + " (" + cotation.getMnemonique() + ")","", "", data, true);
		final XYPlot xyplot = chart.getXYPlot();

		CandlestickRenderer renderer = new CandlestickRenderer();
		renderer.setDrawVolume(false);

		renderer.setSeriesStroke(0, new BasicStroke(0.001f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
		renderer.setSeriesPaint(0, Color.black);

		renderer.setSeriesPaint(0,  new Color(0x000000));

		xyplot.getRangeAxis().setAutoRange(false);
		xyplot.getRangeAxis().setRange(lowest * 0.9, uppest * 1.1);
		xyplot.getDomainAxis().setAutoRange(false);

		xyplot.getRangeAxis().setAutoRange(false);
		xyplot.getDomainAxis().setAutoRange(false);
		renderer.setSeriesToolTipGenerator(0, new HighLowItemLabelGenerator(new SimpleDateFormat("MM/dd/yyyy"),new DecimalFormat("0.00")) {
			private static final long serialVersionUID = 1L;
			public String generateToolTip(XYDataset dataset, int series, int item) {
				DefaultHighLowDataset data = (DefaultHighLowDataset) dataset;
				String toolTipStr = "Date: " +  new SimpleDateFormat("MM/dd/yyyy").format(data.getXDate(series, item)) + " ";
				toolTipStr += "Ouverture: " + new DecimalFormat("0.00").format(data.getOpenValue(series, item)) + " \n";
				toolTipStr += "Cloture: " + new DecimalFormat("0.00").format(data.getCloseValue(series, item)) + " \n";
				toolTipStr += "Plus haut: " + new DecimalFormat("0.00").format(data.getHighValue(series, item)) + " \n";
				toolTipStr += "Plus bas: " + new DecimalFormat("0.00").format(data.getLowValue(series, item)) + " \n";
				return toolTipStr;
			}
		});
		xyplot.setRenderer(0,renderer);
		xyplot.setRangeCrosshairLockedOnData(true);
		xyplot.getRenderer().setSeriesPaint(0, Color.BLACK);
		/* Ajout des indicateurs sur le graphique */
		for(int numIndicateur =0 ; numIndicateur < indicateursSurCours.size() ; ++numIndicateur){
			IndicateurSurCours ind = indicateursSurCours.get(numIndicateur);

			xyplot.setDataset(numIndicateur+1, ind.getDataset()); 

			renderer.setSeriesStroke(numIndicateur+1, new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
			renderer.setSeriesPaint(numIndicateur+1, Color.red);
			XYToolTipGenerator tooltipGenerator= new StandardXYToolTipGenerator("Date : {1}," + ind.getNomIndicateur() + "(" +  ind.getPeriode() + ")" + ": {2}", new SimpleDateFormat("MM/dd/yyyy"),new DecimalFormat("0.00")); 
			xyplot.setRenderer(numIndicateur+1,new StandardXYItemRenderer(StandardXYItemRenderer.LINES,tooltipGenerator));
			xyplot.mapDatasetToRangeAxis(numIndicateur+1, 0); 
		}
		
		xyplot.setBackgroundPaint(new Color(150, 150, 150));


		chartPanel = new ChartPanel(chart);
		chartPanel.setMouseZoomable(true);
		chartPanel.setPreferredSize(new Dimension((int) (parent.getScreenSize().width * WIDTH),
					   					(int) (parent.getScreenSize().height * HEIGHT *2/3)));
		
		BorderLayout g = new BorderLayout();
		this.setLayout(g);
		this.add(chartPanel,BorderLayout.NORTH);

		ind = new JPanel();
		ind.setSize(new Dimension((int) (parent.getScreenSize().width * WIDTH),
					   					(int) (parent.getScreenSize().height * HEIGHT  *0.33)));
		
		GridLayout gl = new GridLayout(chartIndicateurs.size(),1);
		ind.setLayout(gl);
		// chaque composant supplémentaire occupe 0.33 / nbComposant 
		for(int i = 0 ; i<chartIndicateurs.size(); ++i) {
			IndicateursSup is = chartIndicateurs.get(i);
			Dimension d = new Dimension((int) (parent.getScreenSize().width * WIDTH),
					   					(int) (parent.getScreenSize().height * HEIGHT ));
			
			ind.add(is.getPanel(d));			
		}
		this.add(ind,BorderLayout.CENTER);
		

		this.resize(new Dimension((int) (parent.getScreenSize().width * WIDTH + 1),
									 (int) (parent.getScreenSize().height * HEIGHT )));
	}

	public Cotation getCotation() {
		return cotation;
	}

	public void setCotation(Cotation c) {
		cotation = c;
	}

	public void setDuree(Duree duree) {
		this.duree = duree;
	}	

	public void setDonnees(Cotation c, Duree duree) {
		this.duree		= duree;
		chartIndicateurs = new ArrayList<IndicateursSup>();
		this.cotation	= c;
	}

	public void componentHidden(ComponentEvent e) {
	}

	public void componentMoved(ComponentEvent e) {
	}

	public void componentResized(ComponentEvent e) {
		build();
	}

	public void componentShown(ComponentEvent e) {
	}
}
